using System;
using System.Windows.Media;
using System.Windows;
using System.Windows.Controls.Primitives;
using System.Windows.Input;
using Microsoft.Practices.Composite.Presentation.Commands;
using Microsoft.Practices.Composite.Regions;
using Shatkotha.WPF.Global.Bases;

namespace Shatkotha.WPF.Global.Common.Controls.Dialog
{
    public class DialogPresenter:APresenter,IDialogPresenter
    {
        private bool _isOkayButtonEnabled = true;
        public bool IsOkayButtonEnabled 
        { 
            get
            {
                return _isOkayButtonEnabled;
            } 
            set
            {
                _isOkayButtonEnabled = value;
                DialogCommand.RaiseCanExecuteChanged();
            }
        }
        public DialogPresenter(IDialogView view,IRegionManager regionManager)
            :base(view)
        {
            DialogView = view;
            RegionManager = regionManager;
            DialogCommand =  new DelegateCommand<object>(ExecuteCommand,CanExecuteCommand);
            PopupContainer = new Window
                                 {
                                     AllowsTransparency = true,
                                     Content = view as UIElement,
                                     WindowStyle = WindowStyle.None,
                                     ShowInTaskbar = false,
                                     Background = new SolidColorBrush(Colors.Transparent),
                                     Padding = new Thickness(0),
                                     Margin = new Thickness(0),
                                     WindowState = WindowState.Normal,
                                     WindowStartupLocation= WindowStartupLocation.CenterOwner,
                                     SizeToContent= SizeToContent.WidthAndHeight
                                 };
            PopupContainer.Activated += PopupContainerActivated;
            SetButtonContentProperties();
        }

        private bool CanExecuteCommand(object arg)
        {
            if ((DialogResult)arg == DialogResult.OK)
            {
                return IsOkayButtonEnabled;
            }
            return true;
        }



        void PopupContainerActivated(object sender, EventArgs e)
        {
            _presenter.OnActivated();
        }

        private void SetButtonContentProperties()
        {
            YesButtonCaption = StringTable.YesButtonCaption;
            NoButtonCaption = StringTable.NoButtonCaption;
            OkButtonCaption = StringTable.OkButtonCaption;
            CancelButtonCaption = StringTable.CancelButtonCaption;
            IgnoreButtonCaption = StringTable.IgnoreButtonCaption;
            AbortButtonCaption = StringTable.AbortButtonCaption;
            RetryButtonCaption = StringTable.RetryButtonCaption;
        }

        private Window PopupContainer { get; set; }
        private IDialogView DialogView { get; set; }
        public IRegionManager RegionManager { get; set; }
        public DelegateCommand<object> DialogCommand { get; set; }

        private void ExecuteCommand(object parameter)
        {
            DialogResult = (DialogResult)parameter;
            if (DialogContentPresenter == null)
            {
                PopupContainer.Close();
                SetValue(UserViewProperty, null);
            }
            else if (DialogContentPresenter.OnClosing(DialogResult))
            {
                PopupContainer.Close();
                SetValue(UserViewProperty, null);
            }
        }

        #region IDialogPresenter Members

        public DialogResult ShowModal(IDialogContentPresenter presenter)
        {
            return Show(presenter, "", DialogButton.None, true);
        }

        public IDialogContentPresenter DialogContentPresenter { get; set; }

        private DialogResult Show(IDialogContentPresenter presenter, string title, DialogButton dialogButton, bool isModal)
        {
            _presenter = presenter;

            PopupContainer.Owner = Application.Current.MainWindow;

            if (isModal)
                DisableWindow();
            if(IsMouseCaptureOn)
            {
                CaptureOnElement = View as UIElement;
                SetMouseCaptureOn();
            }
            DialogContentPresenter = presenter;
            presenter.DialogResultEvent += DialogContainerPresenterDialogResultEvent;

            SetProperties(presenter.View, title, dialogButton);

            presenter.OnShowing();

            if (isModal)
            {
                PopupContainer.ShowDialog();
                SetValue(UserViewProperty, null);
                EnableWindow();
                SetMouseCaptureOff();
            }
            else
                PopupContainer.Show();

            return DialogResult;
        }
        private bool DisabledWindow { set; get; }

        private void DisableWindow()
        {
            //if (Application.Current.IsWindowEnabled())
            //{
            //    Application.Current.DisableWindow();
            //    DisabledWindow = true;
            //}
        }
        private void EnableWindow()
        {
            //if (DisabledWindow && Application.Current.IsWindowEnabled() == false)
            //{
            //    Application.Current.EnableWindow();
            //    DisabledWindow = false;
            //}
        }

        #region Mouse Capture
        private UIElement CaptureOnElement { set; get; }
        private void SetMouseCaptureOn()
        {
            if (CaptureOnElement == null) return;

            var uiView = CaptureOnElement;            
            uiView.PreviewMouseDown += UIViewPreviewMouseDown;
            uiView.MouseLeave += UIViewMouseLeave;
            uiView.MouseWheel += UiViewMouseWheel;
            Mouse.Capture(uiView, CaptureMode.SubTree);
        }

        private void SetMouseCaptureOff()
        {
            if (CaptureOnElement == null) return;
            var uiView = CaptureOnElement;
            uiView.PreviewMouseDown -= UIViewPreviewMouseDown;
            uiView.MouseLeave -= UIViewMouseLeave;
            uiView.MouseWheel -= UiViewMouseWheel;
            Mouse.Capture(null);
            CaptureOnElement = null;
        }

        private void UiViewMouseWheel(object sender, MouseWheelEventArgs e)
        {
            e.Handled = true;
        }

        private void UIViewMouseLeave(object sender, MouseEventArgs e)
        {
            if (CaptureOnElement == null)
                return;
            if (IsMouseCaptureOn)
            {
                if (Mouse.Captured != CaptureOnElement)
                    Mouse.Capture(CaptureOnElement, CaptureMode.SubTree);
            }
        }
        private bool IsInViewArea(Point point, Size renderSize)
        {
            var rect = new Rect(new Point(0, 0), renderSize);
            return rect.Contains(point);
        }
        private void UIViewPreviewMouseDown(object sender, MouseButtonEventArgs e)
        {
            if(CaptureOnElement == null)
                return;
            if (IsMouseCaptureOn)
            {
                Point point = e.GetPosition(CaptureOnElement);
                if (IsInViewArea(point, CaptureOnElement.RenderSize) == false)
                {
                    e.Handled = true;
                }
            }
        }
        
        #endregion
        void DialogContainerPresenterDialogResultEvent(object sender, GenericEventArgs<DialogResult> e)
        {
            DialogResult = e.Data;
            
            if(IsMouseCaptureOn)
                SetMouseCaptureOff();

            if (DialogContentPresenter != null && DialogContentPresenter.OnClosing(DialogResult))
            {
                SetValue(UserViewProperty, null);
                PopupContainer.Close();
            }            
        }

        #endregion

        #region IDialogPresenter Members

        public DialogResult DialogResult { get; private set; }

        #endregion

        public PlacementMode Placement
        {
            get 
            {
                return (PlacementMode) GetValue(PlacementProperty);
            }
            set
            {
                SetValue(PlacementProperty, value);
            }
        }

        public bool IsMouseCaptureOn { set; get; }

        public string YesButtonCaption 
        {
            get
            {
                return GetValue(YesButtonCaptionProperty).ToString();
            }
            set
            {
                SetValue(YesButtonCaptionProperty, value);
            }
        }

        public string NoButtonCaption
        {
            get
            {
                return GetValue(NoButtonCaptionProperty).ToString();
            }
            set
            {
                SetValue(NoButtonCaptionProperty, value);
            }
        }

        public string OkButtonCaption
        {
            get
            {
                return GetValue(OkButtonCaptionProperty).ToString();
            }
            set
            {
                SetValue(OkButtonCaptionProperty, value);
            }
        }

        public string CancelButtonCaption
        {
            get
            {
                return GetValue(CancelButtonCaptionProperty).ToString();
            }
            set
            {
                SetValue(CancelButtonCaptionProperty, value);
            }
        }

        public string IgnoreButtonCaption
        {
            get
            {
                return GetValue(IgnoreButtonCaptionProperty).ToString();
            }
            set
            {
                SetValue(IgnoreButtonCaptionProperty, value);
            }
        }

        public string AbortButtonCaption
        {
            get
            {
                return GetValue(AbortButtonCaptionProperty).ToString();
            }
            set
            {
                SetValue(AbortButtonCaptionProperty, value);
            }
        }

        public string RetryButtonCaption
        {
            get
            {
                return GetValue(RetryButtonCaptionProperty).ToString();
            }
            set
            {
                SetValue(RetryButtonCaptionProperty, value);
            }
        }

        public static readonly DependencyProperty PlacementProperty = DependencyProperty.Register(
            "Placement",
            typeof(PlacementMode),
            typeof(DialogPresenter),
            new PropertyMetadata(PlacementMode.Center)
            );
        public static readonly DependencyProperty PlacementTargetProperty = DependencyProperty.Register(
            "PlacementTarget",
            typeof(UIElement),
            typeof(DialogPresenter)            
            );
        public static readonly DependencyProperty TitlebarVisibilityProperty = DependencyProperty.Register(
            "TitlebarVisibility",
            typeof (Visibility),
            typeof (DialogPresenter),
            new PropertyMetadata(Visibility.Visible)
            );

        public static readonly DependencyProperty YesButtonCaptionProperty = DependencyProperty.Register(
            "YesButtonCaption",
            typeof(string),
            typeof(DialogPresenter));

        public static readonly DependencyProperty NoButtonCaptionProperty = DependencyProperty.Register(
            "NoButtonCaption",
            typeof(string),
            typeof(DialogPresenter));

        public static readonly DependencyProperty OkButtonCaptionProperty = DependencyProperty.Register(
            "OkButtonCaption",
            typeof(string),
            typeof(DialogPresenter));

        public static readonly DependencyProperty CancelButtonCaptionProperty = DependencyProperty.Register(
            "CancelButtonCaption",
            typeof(string),
            typeof(DialogPresenter));

        public static readonly DependencyProperty IgnoreButtonCaptionProperty = DependencyProperty.Register(
            "IgnoreButtonCaption",
            typeof(string),
            typeof(DialogPresenter));

        public static readonly DependencyProperty AbortButtonCaptionProperty = DependencyProperty.Register(
            "AbortButtonCaption",
            typeof(string),
            typeof(DialogPresenter));

        public static readonly DependencyProperty RetryButtonCaptionProperty = DependencyProperty.Register(
            "RetryButtonCaption",
            typeof(string),
            typeof(DialogPresenter));
        public static readonly DependencyProperty UserViewProperty = DependencyProperty.Register(
            "UserView",
            typeof(UIElement),
            typeof(DialogPresenter));
        public static readonly DependencyProperty TitleProperty = DependencyProperty.Register(
            "Title",
            typeof(string),
            typeof(DialogPresenter));
        public static readonly DependencyProperty CommandPanelVisibilityProperty = DependencyProperty.Register(
            "CommandPanelVisibility",
            typeof(Visibility),
            typeof(DialogPresenter));
        public static readonly DependencyProperty OkButtonVisibilityProperty = DependencyProperty.Register(
            "OkButtonVisibility",
            typeof(Visibility),
            typeof(DialogPresenter));
        public static readonly DependencyProperty CancelButtonVisibilityProperty = DependencyProperty.Register(
            "CancelButtonVisibility",
            typeof(Visibility),
            typeof(DialogPresenter));
        public static readonly DependencyProperty YesButtonVisibilityProperty = DependencyProperty.Register(
            "YesButtonVisibility",
            typeof(Visibility),
            typeof(DialogPresenter));
        public static readonly DependencyProperty NoButtonVisibilityProperty = DependencyProperty.Register(
            "NoButtonVisibility",
            typeof(Visibility),
            typeof(DialogPresenter));
        public static readonly DependencyProperty IgnoreButtonVisibilityProperty = DependencyProperty.Register(
            "IgnoreButtonVisibility",
            typeof(Visibility),
            typeof(DialogPresenter));
        public static readonly DependencyProperty RetryButtonVisibilityProperty = DependencyProperty.Register(
            "RetryButtonVisibility",
            typeof(Visibility),
            typeof(DialogPresenter));
        public static readonly DependencyProperty AbortButtonVisibilityProperty = DependencyProperty.Register(
            "AbortButtonVisibility",
            typeof(Visibility),
            typeof(DialogPresenter));

        private IDialogContentPresenter _presenter;

        #region IDialogPresenter Members


        public void Show(IDialogContentPresenter presenter)
        {
            Show(presenter, "", DialogButton.None, false);
        }

        public void Show(IDialogContentPresenter presenter, string title)
        {
            Show(presenter, title, DialogButton.None, false);
        }

        #endregion

        #region IDialogPresenter Members


        public void DoDragDelta(DragDeltaEventArgs e)
        {
            PopupContainer.Left = PopupContainer.Left + e.HorizontalChange;
            PopupContainer.Top = PopupContainer.Top + e.VerticalChange;
        }

        public Visibility TitleBarVisibility
        {
            get
            {
                return (Visibility) GetValue(TitlebarVisibilityProperty);
            }
            set 
            { 
                SetValue(TitlebarVisibilityProperty, value);
            }
        }

        public UIElement PlacementTarget
        {
            get
            {
                return (UIElement) GetValue(PlacementTargetProperty);
            }
            set 
            { 
                SetValue(PlacementTargetProperty,value);
            }
        }

        #endregion

        #region IDialogPresenter Members


        public DialogResult ShowModal(IView view)
        {
            return Show(view, "", DialogButton.None, true);
        }

        public DialogResult ShowModal(IView view, string title)
        {
            return Show(view, "", DialogButton.None, true);
        }
        

        public void Show(IView view)
        {
            Show(view, "", DialogButton.None, false);
        }

        public void Show(IView view, string title)
        {
            Show(view, title, DialogButton.None, false);
        }

        public void Show(IView view, string title, bool isModal)
        {
            Show(view, title, DialogButton.None, isModal);
        }
        private DialogResult Show(IView view, string title, DialogButton dialogButton, bool isModal)
        {
            PopupContainer.Owner = Application.Current.MainWindow;

            if (isModal)
                DisableWindow();

            SetProperties(view, title, dialogButton);
            
            if (isModal)
            {
                PopupContainer.ShowDialog();
                EnableWindow();
            }
            else
                PopupContainer.Show();

            SetValue(UserViewProperty, null);
                
            return DialogResult;
        }

        private void SetProperties(IView view, string title, DialogButton dialogButton)
        {
            SetValue(TitleProperty, title);
            SetValue(UserViewProperty, view);

            SetValue(CommandPanelVisibilityProperty, Visibility.Collapsed);
            SetValue(OkButtonVisibilityProperty, Visibility.Collapsed);
            SetValue(CancelButtonVisibilityProperty, Visibility.Collapsed);
            SetValue(YesButtonVisibilityProperty, Visibility.Collapsed);
            SetValue(NoButtonVisibilityProperty, Visibility.Collapsed);
            SetValue(IgnoreButtonVisibilityProperty, Visibility.Collapsed);
            SetValue(RetryButtonVisibilityProperty, Visibility.Collapsed);
            SetValue(AbortButtonVisibilityProperty, Visibility.Collapsed);

            switch (dialogButton)
            {
                case DialogButton.None:
                    break;
                case DialogButton.OK:
                    SetValue(CommandPanelVisibilityProperty, Visibility.Visible);
                    SetValue(OkButtonVisibilityProperty, Visibility.Visible);
                    break;
                case DialogButton.OKCancel:
                    SetValue(CommandPanelVisibilityProperty, Visibility.Visible);
                    SetValue(OkButtonVisibilityProperty, Visibility.Visible);
                    SetValue(CancelButtonVisibilityProperty, Visibility.Visible);
                    break;
                case DialogButton.AbortRetryIgnore:
                    SetValue(CommandPanelVisibilityProperty, Visibility.Visible);
                    SetValue(AbortButtonVisibilityProperty, Visibility.Visible);
                    SetValue(RetryButtonVisibilityProperty, Visibility.Visible);
                    SetValue(IgnoreButtonVisibilityProperty, Visibility.Visible);
                    break;
                case DialogButton.YesNoCancel:
                    SetValue(CommandPanelVisibilityProperty, Visibility.Visible);
                    SetValue(YesButtonVisibilityProperty, Visibility.Visible);
                    SetValue(NoButtonVisibilityProperty, Visibility.Visible);
                    SetValue(CancelButtonVisibilityProperty, Visibility.Visible);
                    break;
                case DialogButton.YesNo:
                    SetValue(CommandPanelVisibilityProperty, Visibility.Visible);
                    SetValue(YesButtonVisibilityProperty, Visibility.Visible);
                    SetValue(NoButtonVisibilityProperty, Visibility.Visible);
                    break;
                case DialogButton.RetryCancel:
                    SetValue(CommandPanelVisibilityProperty, Visibility.Visible);
                    SetValue(RetryButtonVisibilityProperty, Visibility.Visible);
                    SetValue(CancelButtonVisibilityProperty, Visibility.Visible);
                    break;
                default:
                    break;
            }
        }

        #endregion

        #region IDialogPresenter Members

        public DialogResult ShowModal(IDialogContentPresenter presenter, string title)
        {
            return Show(presenter, title, DialogButton.None, true);
        }

        public DialogResult ShowModal(IDialogContentPresenter presenter, string title, DialogButton dialogButton)
        {
            return Show(presenter, title, dialogButton, true);
        }

        public void Show(IDialogContentPresenter presenter, string title, DialogButton dialogButton)
        {
            Show(presenter, title, dialogButton, false);
        }        

        public DialogResult ShowModal(IView view, string title, DialogButton dialogButton)
        {
            return Show(view, title, dialogButton, true);
        }

        public void Show(IView view, string title, DialogButton dialogButton)
        {
            Show(view, title, dialogButton, false);
        }

        #endregion
    }
}